import time
import os
import subprocess
import multiprocessing
from multiprocessing import Pool
from functools import partial
from openpyxl import load_workbook, Workbook
from Microservice_Managers.frontend import *
from Microservice_Managers.adservice import *
from Microservice_Managers.checkoutservice import *
from Microservice_Managers.currencyservice import *
from Microservice_Managers.emailservice import *
from Microservice_Managers.paymentservice import *
from Microservice_Managers.productcatalogservice import *
from Microservice_Managers.cartservice import *
from Microservice_Managers.recommendationservice import *
from Microservice_Managers.shippingservice import *
from Microservice_Managers.rediscart import *
from Adaptive_Resource_Manager import *

# folder_name = '20'
folder_name = '50'
# folder_name = '80'

def Execute(microservice_name, desired_replicas):
    """执行扩容或缩容命令"""
    try:
        execute_command = f"kubectl scale deployment {microservice_name} -n boutique --replicas={desired_replicas}"
        print(f"Executing command: {execute_command}")
        result = subprocess.run(execute_command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(result.stdout.decode())  # 打印命令输出
    except subprocess.CalledProcessError as e:
        print(f"Error executing scale command for {microservice_name}: {e.stderr.decode()}")
    except Exception as e:
        print(f"Error executing scale command for {microservice_name}: {e}")
    return

def run_function(func):
    """运行微服务管理器，并打印结果"""
    try:
        result = func()
        print(f"Running function {func.func.__name__}, result: {result}")
    except Exception as e:
        print(f"Error running function {func.func.__name__}: {e}")
        result = None
    return result

# Smart HPA 的操作逻辑
desired_time = 176000  # Total_Test_Time (sec)
start_time = time.time()

if __name__ == '__main__':
    ARM_saved_decision = []  # 上一次 ARM 的伸缩决策
    row_number = 2  # Excel 中存储结果的行数

    while (time.time() - start_time) < desired_time:
        Test_Time = time.time() - start_time
        print(f"\nRunning test cycle at {Test_Time} seconds")

        # 并行运行各微服务管理器
        functions = [
            partial(frontend, Test_Time, folder_name), partial(adservice, Test_Time, folder_name),
            partial(cartservice, Test_Time, folder_name), partial(currencyservice, Test_Time, folder_name),
            partial(checkoutservice, Test_Time, folder_name), partial(emailservice, Test_Time, folder_name),
            partial(paymentservice, Test_Time, folder_name), partial(shippingservice, Test_Time, folder_name),
            partial(productcatalogservice, Test_Time, folder_name), partial(recommendationservice, Test_Time, folder_name),
            partial(rediscart, Test_Time, folder_name)
        ]
        
        try:
            with multiprocessing.Pool(processes=len(functions)) as pool:
                microservices_data = pool.map(run_function, functions)
                print(f"Collected microservices data: {microservices_data}")
        except Exception as e:
            print(f"Error in multiprocessing pool: {e}")
            continue  # Skip this cycle and try again

        ARM_decision = []  # 当前的伸缩决策

        # 分析每个微服务的资源使用情况
        for i, service_data in enumerate(microservices_data):
            try:
                # 检查 service_data 是否有效
                if not service_data or not isinstance(service_data, dict):
                    print(f"Skipping invalid service data at index {i}")
                    continue

                print(f"Service data at index {i}: {service_data}")  # Debugging line

                # 检查服务是否超出最大副本数限制
                if service_data['desired_replicas'] > service_data['max_replica']:
                    print(f"Resource constraint detected for microservice: {service_data['app_name']}")

                    # 更新 maxR 以便 ARM 决策
                    for k, microservice in enumerate(microservices_data):
                        for decision in ARM_saved_decision:
                            if microservice and microservice['app_name'] == decision['app_name']:
                                microservices_data[k]['max_replica'] = decision['max_replica']
                                print(f"Updated max replicas for {microservice['app_name']} to {microservice['max_replica']}")

                    # 调用 ARM 进行伸缩决策
                    print(f"Passing the following data to ARM: {microservices_data}")
                    ARM_decision = Adaptive_Resource_Manager(microservices_data)
                    print(f"ARM decision: {ARM_decision}")
                    ARM_saved_decision = ARM_decision
                    break  # 找到一个受限服务后退出循环，ARM 已经处理所有服务的决策

            except Exception as e:
                print(f"Error processing service data at index {i}: {e}")
                continue

        # 更新 Excel 并执行扩缩容操作
        for service_data in microservices_data:
            try:
                if not service_data or not isinstance(service_data, dict):
                    continue

                file_path = f'/root/wmxstudy/Smart_HPA/Smart_HPA_Codebase/Knowledge_Base/{folder_name}/{service_data["app_name"]}.xlsx'
                try:
                    workbook = load_workbook(file_path)
                except FileNotFoundError:
                    workbook = Workbook()
                    workbook.save(file_path)
                    workbook = load_workbook(file_path)

                sheet = workbook.active
                sheet.cell(row=row_number, column=1, value=Test_Time)  # 测试时间
                sheet.cell(row=row_number, column=2, value=service_data['cpu_request'])  # CPU 请求
                sheet.cell(row=row_number, column=3, value=service_data['current_replicas'])  # 当前副本数
                sheet.cell(row=row_number, column=4, value=service_data['desired_replicas'])  # 期望副本数
                sheet.cell(row=row_number, column=5, value=service_data['max_replica'])  # 最大副本数
                sheet.cell(row=row_number, column=6, value=service_data['scaling_action'])  # 伸缩动作
                workbook.save(file_path)
                workbook.close()

                # 执行扩缩容操作
                if service_data['scaling_action'] != "no scale":
                    print(f"Scaling microservice {service_data['app_name']} to {service_data['desired_replicas']} replicas")
                    Execute(service_data['app_name'], service_data['desired_replicas'])

            except Exception as e:
                print(f"Error processing microservice {service_data['app_name']}: {e}")

        row_number += 1
        print("Current ARM decision:", ARM_decision)
